#include "sys_uart.h"
#include "sys_clock.h"
#include "sys_gpio.h"
#include "sys_delay.h"
#include "sys_lcd.h"
#include "sys_timer.h"
#include <string.h>
#include <stdio.h>
#include <sys_mmu.h>
#include "sys_io.h"
//-----------------------
#include "sys_lcd_conf.h"
//-----------------------
#include "ff.h"
#include "videoplayer.h"
#include "sys_defe.h"

//---------JPEG定义---------//
#include "jpegdec_main.h"
#include "f1c100s_malloc.h"
//---------测试图片---------//
#include "test_jpeg1.h" /*480x272-YUV444*/
#include "test_jpeg2.h" /*480x267-YUV422*/
#include "test_jpeg3.h" /*480x272-YUV420*/
#include "test_jpeg4.h" /*1280x720-YUV420*/

/*-----------------------------------------------------------------------
1.可在sys_lcd_conf.h文件定义LCD分辩率大小,支持RGB480x272,RGB800x480,RGB1024x600分辩率;
------------------------------------------------------------------------*/

/*---------------------------------1,JPEG解码---------------------------------------
1.图片使用Bin2C.exe转-JPEG图片目前只支持YUV420,YUV411,YUV422,YUV444压缩格式;
2.Y,C,ARGB缓存需要1024字节对齐,JPEG图片缓存需要32字节对齐;
3.自定义malloc分配函数,方便ucos使用,块大小定义为1024可提升分配速度;
4.两个调用方法：
	(1),预先定义内存 Jpeg_decoder_2;
	(2),使用malloc分配内存 Jpeg_decoder 使用后需要释放ARGB缓存;
------------------------------------------------------------------------*/

/*---------------------------------2，视频播放---------------------------------------
1.播放视频需要VideoConverter.exe转换为MJPEG压缩的AVI格式，音频为16位无压缩PCM格式，参考设置说明;
2.视频解码后直接输出到DEFE-DEBE-TCON显示,可以缩放与调整位置;
3.测试的视频文件放在TF卡的【根目录/video/"】目录里面,测试的视频文件下载地址【链接：https://pan.baidu.com/s/18rA8OCNy005mX5ebmb57hg
提取码：wrvh】;
------------------------------------------------------------------------*/

/*------------------------------------------------------------------------
修改记录：
2020-04-15
	1.解决视频画面出现撕裂情况，修改视频帧为多缓存;
	2.解决退出播放时花屏，增加defe退出函数;
	3.改800x480闪屏问题;
	  (1).mmu里面CACHE_WRITE_THROUGH改CACHE_WRITE_BACK模式;
		(2).减小LCD时钟;
		(3).大分辩率时使用单图层;
2020-07-08
	1.JPEG图片解码增加YUV411,YUV422,YUV444的解码;
2020-07-22
	1.加入LCD-RGB-1024x600支持;
2020-08-13
	1.大分辩率图片解码失败,解决方法:解码函数增加超时;
2020-08-14
	1.增加获取图片宽高函数;
2020-08-24
	1.jpeg_add.c中增加macc_printf打印函数-可控制是否打印输出;
	2.增加Jpeg_Dec_Other_tasks()硬件解码时的空闲函数,
		（1）-纯裸机时函数里调用延时(1ms)或处理其它事情;
		（2）-OS系统时加入系统延时函数(1ms),完成任务切换;
	3.图片解码完成后调用eLIBs_CleanDCacheRegion(0,0)写通cache后再送显示,避免图像出现线条;
2020-08-29
	增加OS调用宏定义:
		1.OS调用时 FAT_FS_OS = 1 ,为FAT_FS文件系统重定义内存分配函数
	2.OS调用时 AVI_PLAY_OS = 1 ,为视频播放重定义内存分配函数
	OS调用时的改动：
		1.Defe_Other_tasks->()加入系统延时
		2.AVI_Other_tasks->()加入系统延时
		3.Jpeg_Dec_Other_tasks->()加入系统延时
		4.SD_Other_tasks->()加入系统延时
2021/01/08
		1.屏蔽掉JPEG中MACC_Init中的中断打开函数
------------------------------------------------------------------------*/

__align(1024) unsigned int LCDbuff1[XSIZE_PHYS * YSIZE_PHYS];
/*
显示32色位图片ARGB
*/
void LCD_Draw_Picture(int x, int y, int w, int h, unsigned char *pic)
{
	int i, l, a, b;
	u32 *tpic = (u32 *)pic;
	for (i = 0; i < h; i++) // y
	{
		a = (y + i) * XSIZE_PHYS + x;
		b = w * i;
		for (l = 0; l < w; l++)
			LCDbuff1[a + l] = tpic[b + l];
	}
}
/*--------------------------------------------------------------
JPEG数组
--------------------------------------------------------------*/
unsigned char *jpeg[4] = // 图片指针-图片使用Bin2C.exe转
	{
		test_jpeg1, test_jpeg2, test_jpeg3, test_jpeg4};
int jpeg_len[4] = // 图片大小
	{
		sizeof(test_jpeg1) - 1, sizeof(test_jpeg2) - 1, sizeof(test_jpeg3) - 1, sizeof(test_jpeg4) - 1};
int pos[4][2] = // 拼图时4个图片的坐标
	{
		0,
		0,
		XSIZE_PHYS / 2,
		0,
		0,
		YSIZE_PHYS / 2,
		XSIZE_PHYS / 2,
		YSIZE_PHYS / 2,
};
#if 0 //=1使用malloc分配缓存
/*--------------------------------------------------------------
JPEG解码测试-使用malloc申请内存
480*272解码 输出480x272显示 耗时7ms
1280*720解码 输出480x272显示  耗时30ms
--------------------------------------------------------------*/
void jpegdecorder_test(void)
{
int res=0;
int Time=0,i,l;
unsigned char* out_argb;
int jpeg_w;
int jpeg_h;
int argb_w=XSIZE_PHYS;
int argb_h=YSIZE_PHYS;
	sysprintf("JPEG Decoder Test! [malloc mode]\r\n");
/*--内存管理初始化--*/
	mem_init();
/*--初始化JPEG模块--*/
	MACC_Init(MACC_MODULE_MPEG_DEC);
  Defe_Init();
	while(1)
	{
		for(i=0;i<5;i++)
		{
			if(i<4)
			{
				/*--解码图片--*/
				sysprintf("Decoder START !\r\n");
				Time=Read_time_ms();
				res=Jpeg_decoder(jpeg[i],jpeg_len[i],&jpeg_w,&jpeg_h,//JPEG输入设置
										 &out_argb,argb_w,argb_h,//ARGB输出设置
										 f1c100s_malloc_Align,f1c100s_free,500);//代入内存分配函数
				Time=Read_time_ms()-Time;
				if(res==0)
				{
					sysprintf("Decoder End ,w=%d,h=%d, Time: %d ms !\r\n",jpeg_w,jpeg_h,Time);
					/*--写通cache,避免图像出现线条--*/
					eLIBs_CleanDCacheRegion(0,0);
					/*--显示图片--*/
					LCD_Draw_Picture(0,0,argb_w==0?jpeg_w:argb_w,argb_h==0?jpeg_h:argb_h,out_argb);
				}
				/*--释放图片--*/
				f1c100s_free(out_argb);
				/*--延时--*/
			}else//显示拼图
			{
				for(l=0;l<4;l++)
				{
					/*--解码图片--*/
					res=Jpeg_decoder(jpeg[l],jpeg_len[l],&jpeg_w,&jpeg_h,&out_argb,XSIZE_PHYS/2,YSIZE_PHYS/2,f1c100s_malloc_Align,f1c100s_free,500);
					if(res==0)
					{
						/*--写通cache,避免图像出现线条--*/
						eLIBs_CleanDCacheRegion(0,0);
						/*--显示图片--*/
						LCD_Draw_Picture(pos[l][0],pos[l][1],XSIZE_PHYS/2,YSIZE_PHYS/2,out_argb);
					}
					/*--释放图片--*/
					f1c100s_free(out_argb);
				}
			}
			delay_ms(1000);
		}
	}
	Defe_Exit();
}
#else
/*--------------------------------------------------------------
JPEG解码测试-预先定义内存
480*272解码 输出480x272显示
1280*720解码 输出480x272显示
--------------------------------------------------------------*/
static __align(1024) unsigned char buff_y[get_yc_len(1280, 720)];
static __align(1024) unsigned char buff_c[get_yc_len(1280, 720)];
static __align(1024) unsigned char out_argb[1280 * 720 * 4];
void jpegdecorder_test(void)
{
	int res = 0;
	int Time = 0, i, l;
	int jpeg_w;
	int jpeg_h;
	int argb_w = XSIZE_PHYS;
	int argb_h = YSIZE_PHYS;
	sysprintf("JPEG Decoder Test! [def mode]\r\n");
	/*--初始化JPEG模块--*/
	MACC_Init(MACC_MODULE_MPEG_DEC);
	Defe_Init();
	while (1)
	{
		for (i = 0; i < 5; i++)
		{
			if (i < 4)
			{
				/*--解码图片--*/
				sysprintf("Decoder START !\r\n");
				Time = Read_time_ms();
#if 0
				//获取JPEG宽度高度
				int jwidth,jheight;
				Get_Jpeg_width_height(jpeg[i],jpeg_len[i],&jwidth,&jheight);//会占用1-3ms时间
				sysprintf("Jpeg width: %d height: %d \r\n",jwidth,jheight);
#endif

				res = Jpeg_decoder_2(jpeg[i], jpeg_len[i], &jpeg_w, &jpeg_h, // JPEG输入设置
									 out_argb, argb_w, argb_h,				 // ARGB输出设置
									 buff_y, buff_c, 500);					 // 代入YC缓存
				Time = Read_time_ms() - Time;
				if (res == 0)
				{
					sysprintf("Decoder End ,w=%d,h=%d, Time: %d ms !\r\n", jpeg_w, jpeg_h, Time);
					/*--写通cache,避免图像出现线条--*/
					eLIBs_CleanDCacheRegion(0, 0);
					/*--显示图片--*/
					LCD_Draw_Picture(0, 0, argb_w == 0 ? jpeg_w : argb_w, argb_h == 0 ? jpeg_h : argb_h, out_argb);
				}
				/*--延时--*/
			}
			else // 显示拼图
			{
				for (l = 0; l < 4; l++)
				{
					/*--解码图片--*/
					res = Jpeg_decoder_2(jpeg[l], jpeg_len[l], &jpeg_w, &jpeg_h, out_argb, XSIZE_PHYS / 2, YSIZE_PHYS / 2, buff_y, buff_c, 500);
					if (res == 0)
					{
						/*--写通cache,避免图像出现线条--*/
						eLIBs_CleanDCacheRegion(0, 0);
						/*--显示图片--*/
						LCD_Draw_Picture(pos[l][0], pos[l][1], XSIZE_PHYS / 2, YSIZE_PHYS / 2, out_argb);
					}
				}
			}
			delay_ms(1000);
		}
	}
	Defe_Exit();
}
#endif

/*---------------------------------------------------
AHB 时钟为204MHZ(LCD)
APB 时钟为102MHZ(UART)
---- main
---- main
----------------------------------------------------*/
FATFS fs;
int main(void)
{
	unsigned int CPU_Frequency_hz = 600 * 1000000; // HZ
	Sys_Clock_Init(CPU_Frequency_hz);
	sys_mmu_init();

	Sys_Uart_Init(UART0, CPU_Frequency_hz, 115200, 0);
	Sys_SET_UART_DBG(UART0);

	sysprintf("\r\n\r\n\r\n");
	sysprintf("Sys_Start...\r\n");
	sysprintf("Dram Init Size %d Mb.\r\n", 32);

	Sys_Timer1_Init();

	GPIO_Congif(GPIOE, GPIO_Pin_5, GPIO_Mode_OUT, GPIO_PuPd_NOPULL);
	GPIO_Congif(GPIOE, GPIO_Pin_6, GPIO_Mode_OUT, GPIO_PuPd_NOPULL);
	GPIO_Congif(GPIOE, GPIO_Pin_11, GPIO_Mode_OUT, GPIO_PuPd_NOPULL);

	GPIO_SET(GPIOE, GPIO_Pin_5);
	GPIO_SET(GPIOE, GPIO_Pin_6);
	GPIO_SET(GPIOE, GPIO_Pin_11);

	// 按键初始化【开发板上S10】-切换下一个视频
	GPIO_Congif(GPIOE, GPIO_Pin_3, GPIO_Mode_IN, GPIO_PuPd_UP);
	// LCD初始化
	Sys_LCD_Init(XSIZE_PHYS, YSIZE_PHYS, (unsigned int *)LCDbuff1, NULL);
	Set_Layer_format(0, 0xA, 5); // 设置层0为ARGB8888
#if 1							 /*JPEG图片解码测试*/
	jpegdecorder_test();
#else /*avi-Mjpeg视频播放测试，s10按键切换下一个视频*/
	if (f_mount(&fs, "0:", 1) == 0)
	{

		sysprintf("文件系统挂载成功...\r\n");
		while (1)
		{
#define dposx ((XSIZE_PHYS - 480) / 2)
#define dposy ((YSIZE_PHYS - 272) / 2)

			video_play_avi_mjpeg(0, 0, XSIZE_PHYS, YSIZE_PHYS, (u8 *)"0:/video/v0.avi"); // 854x480
			video_play_avi_mjpeg(dposx, dposy, 480, 272, (u8 *)"0:/video/m0.avi");		 // 480x272
			video_play_avi_mjpeg(dposx, dposy, 480, 272, (u8 *)"0:/video/m1.avi");		 // 480x272
			video_play_avi_mjpeg(dposx, dposy, 480, 272, (u8 *)"0:/video/m2.avi");		 // 480x272
			video_play_avi_mjpeg(dposx, dposy, 480, 272, (u8 *)"0:/video/m3.avi");		 // 480x272
			video_play_avi_mjpeg(dposx, dposy, 480, 272, (u8 *)"0:/video/m4.avi");		 // 480x272
			video_play_avi_mjpeg(dposx, dposy, 480, 272, (u8 *)"0:/video/m5.avi");		 // 480x272
			video_play_avi_mjpeg(dposx, dposy, 480, 272, (u8 *)"0:/video/m6.avi");		 // 480x272
			video_play_avi_mjpeg(0, 0, XSIZE_PHYS, YSIZE_PHYS, (u8 *)"0:/video/g0.avi"); // 1024x768
		}
	}
	else
		sysprintf("没有文件系统..\r\n");
#endif
}
